﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using TagThisOrgProject.Models;
using TagThisOrgProject.Models.ViewModel;

namespace TagThisOrgProject.Repository
{
    public class GlobalRepository
    {
        public TagContext Context { get; set; }

        public UrlRepository UrlRepo { get; set; }
        public TagRepository TagRepo { get; set; }
        public UserBookmarkRepository UserBookmrksRepo { get; set; }
        public UserRepository UserRepo { get; set; }
        public BookmarkRepository BookmarkRepo { get; set; }


        public GlobalRepository()
        {
            this.Context = new TagContext();
        }
        public IEnumerable<UserBookmark> AddBookmarksForUser(string userName, string url, bool isPrivate, params string[] tags)
        {
            return AddBookmarksForUser(userName, url, "", isPrivate, tags);
        }

        public IEnumerable<UserBookmark> AddBookmarksForUser(string userName, string url, string title, bool isPrivate, params string[] tags)
        {
            if (this.BookmarkRepo == null)
                this.BookmarkRepo = new BookmarkRepository(this.Context);
            if (this.UserBookmrksRepo == null)
                this.UserBookmrksRepo = new UserBookmarkRepository(this.Context);

            var bkmrks = this.BookmarkRepo.AddBookmarks(url, isPrivate, tags);
            var usrBkmrks = this.UserBookmrksRepo.AddUserBookmarks(userName, bkmrks.ToArray());

            return usrBkmrks;
        }
        public IEnumerable<Url> SearchUrl()
        {
            // это на будущее. надо будет сделать dsl по тегам.
            return Context.Url.SqlQuery("").Select(u => u);
        }

        public IEnumerable<IGrouping<Url, Bookmark>> SearchUrlByTag(params string[] tags)
        {
            if (this.TagRepo == null)
                this.TagRepo = new TagRepository(this.Context);
            if (this.BookmarkRepo == null)
                this.BookmarkRepo = new BookmarkRepository(this.Context);

            var Tags = TagRepo.GetTags(tags);
            return BookmarkRepo.GetPublicBookmarks(Tags.ToArray())
                .GroupBy(b => b.Url)
                .Where(g => g.Count() == tags.Count())
                .Select(g=>g)                ;
        }
        public UrlPageViewModel SearchUrl(int currentPage, byte take = 10, params string[] tags)
        {
            var searchResultRaw = this.SearchUrlByTag(tags);
            //выбрасывается ошибка, из-за того что ключом использовалась группа.
            // пофиксил, теперь ключ(временно) идентефикатор url подумать как исправить.
            var count = 1;


            var tmp2 = searchResultRaw.Skip((currentPage - 1) * take)
                      .Take(take)
                      .Select(q =>
                          new UrlViewModel(
                              q.Key.Link,
                              q.Key.Favicon,
                              q.Key.PrintScreenUrl,
                              q.Key.Title,
                              q.Key.Description,
                              q.Key.Bookmarks.Select(t => new TagViewModel(
                                  t.Tag.TagId, t.Tag.Text)
                                  ).ToArray()
                                  )).ToList();


            //var tmp = searchResultRaw
            //    .Skip((currentPage-1) * take)
            //    .Take(take)
            //    .Select(g =>
            //    new UrlViewModel(
            //        g.Key.Link,
            //        g.Key.Favicon,
            //        g.Key.PrintScreenUrl,
            //        g.Key.Title,
            //        g.Key.Description,
            //        g.Select(b =>
            //            new TagViewModel(b.Tag.TagId,
            //                b.Tag.Text))
            //                .ToArray())
            //    ).ToList();

            //.ToLookup(k => k.Key, e => e.Select(b => b.Tag));
            return new UrlPageViewModel(tmp2, currentPage + 1, count, take);


        }

        public KeyValuePair<string, string> SearchTitle(string url)
        {
            if (UrlRepo == null)
                UrlRepo = new UrlRepository(this.Context);
            if (UrlRepo.isUrl(url))
            {
                var u = UrlRepo.GetUrl(url);
                if (u != null)
                    return new KeyValuePair<string, string>("ok", u.Title);
                HttpClient hc = new HttpClient();
                var firstResult = hc.GetStringAsync(url);
                var lastResult = firstResult.ContinueWith(t =>
                {
                    var one = "<title>";
                    var two = "</title>";
                    if (t.IsCanceled)
                    {
                        return new KeyValuePair<string, string>("error", "Сайт не доступен. Time out.");
                    }
                    if (t.Exception != null)
                    {
                        return new KeyValuePair<string, string>("error", "Сайт не доступен.");
                    }
                    if (t.IsFaulted)
                    {
                        return new KeyValuePair<string, string>("error", "Сайт не доступен.");
                    }
                    var l = t.Result;
                    if (string.IsNullOrEmpty(l))
                    {
                        return new KeyValuePair<string, string>("error", "Заголовок сайта пуст.");
                    }

                    var first = l.IndexOf(one, StringComparison.OrdinalIgnoreCase);
                    if (first < 0)
                    {
                        return new KeyValuePair<string, string>("error", "Заголовок сайта отсутствует.");
                    }
                    var second = l.IndexOf(two, StringComparison.OrdinalIgnoreCase);
                    if (second < 0)
                    {
                        return new KeyValuePair<string, string>("error", "Заголовок сайта отсутствует.");
                    }

                    return new KeyValuePair<string, string>("ok", l.Substring(first + one.Length, second - (first + one.Length)).Trim());
                });
                if (lastResult.Result.Key.Equals("ok") || lastResult.Result.Value.Contains("Заголовок"))
                {
                    var l = new Task(() =>
                    {
                        this.UrlRepo.AddUrlWithoutSearching(url.Trim(' ', '/').ToLower(), lastResult.Result.Key.Equals("ok") ? lastResult.Result.Value :  string.Empty);
                    });
                    Task.WhenAll(l);
                }

                return lastResult.Result;
            }
            return new KeyValuePair<string, string>("error", "Строка не является URL");
        }

    }
}